package com.louis.iread.bean;

import android.databinding.BindingAdapter;
import android.support.annotation.NonNull;
import android.util.Log;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.louis.iread.IReadApplication;
import com.louis.iread.R;
import com.louis.iread.net.HttpUtil;
import com.louis.iread.utils.DateUtil;
import com.louis.iread.utils.DbUtil;
import com.louis.iread.utils.NovelUtil;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.xutils.db.annotation.Column;
import org.xutils.db.annotation.Table;
import org.xutils.db.sqlite.WhereBuilder;
import org.xutils.ex.DbException;
import org.xutils.image.ImageOptions;
import org.xutils.x;

import java.io.IOException;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import taobe.tec.jcc.JChineseConvertor;

/**
 * Created by louis on 17-3-30.
 */
@Table(name = "book")
public class Book implements Serializable,Comparable {
    public static int TYPE_LOCAL = 0;   //小说在本地
    public static int TYPE_REMOTE = 1;  //小说未下载
    @Column(name = "id", isId = true)
    private Long id;    //小说id

    @Column(name = "novelName")
    private String novelName;   //小说名

    @Column(name = "author")
    private String author;  //小说作者

    @Column(name = "site")
    private String site;    //小说来源网站

    @Column(name = "desc")
    private String desc;    //简介

    @Column(name = "mainUrl", property = "UNIQUE")
    private String mainUrl; //小说主页url

    @Column(name = "contentsUrl", property = "UNIQUE")
    private String contentsUrl; //目录url

    @Column(name = "type")
    private String type;    //小说类型

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    @Column(name = "state")
    private String state;

    @Column(name = "coverUrl")
    private String coverUrl;    //封面url

    @Column(name = "addTime")
    private String addTime;  //小说加入书架日时间

    @Column(name = "readTime")
    private String readTime;   //最后一次打开小说时间

    @Column(name = "updateTime")
    private String updateTime;   //小说更新时间

    @Column(name = "readingArticleIndex")
    private int readingArticleIndex;  //正在阅读的小说章节id, 在目录中的排号,不是articleId

    @Column(name = "readingArticleWordNum")
    private int readingArticleWordNum; //正在阅读的章节的进度, 章节字数

    @Column(name = "isRead")
    private boolean isRead = false; //是否读过

    public boolean isUpdateTag() {
        return updateTag;
    }

    public void setUpdateTag(boolean updateTag) {
        this.updateTag = updateTag;
    }

    @Column(name = "updateTag")
    private boolean updateTag = false;  //是否有更新

    private String latestArticle;   //最新章节

    private String progress;    //章节阅读进度

    private List<Article> mArticles;

    public boolean isRead() {
        return isRead;
    }

    public void setRead(boolean read) {
        isRead = read;
    }

    public String getProgress() {
        try {
            Long num = DbUtil.getDbManager().selector(Article.class).where("bookId", "=", this.id).count();
            Long currentProgress;
            if (isRead())
            {
                currentProgress = (long)readingArticleIndex;
                currentProgress++;
            }
            else
            {
                currentProgress = 0L;
            }
            progress = String.format("%d/%d", currentProgress, num);
            return progress;
        } catch (DbException e) {
            e.printStackTrace();
        }
        return "error occured";
    }

    public void setProgress(String progress) {
        this.progress = progress;
    }

    /*
    获取目录中的最新章节
     */
    public String getLatestArticle(){
        try {
            Article article = DbUtil.getDbManager().selector(Article.class).where("bookId", "=", this.id).orderBy("id", true).findFirst();
            if (article != null) {
                String latestArticleTitle = article.getTitle();
                if (latestArticleTitle != null) {
                    if (IReadApplication.bIsTraditional) {
                        try {
                            return JChineseConvertor.getInstance().s2t(latestArticleTitle);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    return latestArticleTitle;
                }
            }
        } catch (DbException e) {
            e.printStackTrace();
        }

        return "error occured";
    }

    public void setLatestArticle(String latestArticle) {
        this.latestArticle = latestArticle;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNovelName() {
        if (IReadApplication.bIsTraditional) {
            try {
                return JChineseConvertor.getInstance().s2t(novelName);
            } catch (IOException e) {
                e.printStackTrace();
                return novelName;
            }
        }
        return novelName;
    }

    public void setNovelName(String novelName) {
        this.novelName = novelName;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getSite() {
        return site;
    }

    public void setSite(String site) {
        this.site = site;
    }

    public String getDesc() {
        if (IReadApplication.bIsTraditional) {
            try {
                return JChineseConvertor.getInstance().s2t(desc);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getMainUrl() {
        return mainUrl;
    }

    public void setMainUrl(String mainUrl) {
        this.mainUrl = mainUrl;
    }

    public String getContentsUrl() {
        return contentsUrl;
    }

    public void setContentsUrl(String contentsUrl) {
        this.contentsUrl = contentsUrl;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getCoverUrl() {
        return coverUrl;
    }

    public void setCoverUrl(String coverUrl) {
        this.coverUrl = coverUrl;
    }

    public String getAddTime() {
        return addTime;
    }

    public void setAddTime(String addTime) {
        this.addTime = addTime;
    }

    public String getReadTime() {
        if (readTime == null) {
            return "";
        }
        return readTime;
    }

    public void setReadTime(String readTime) {
        this.readTime = readTime;
    }

    public String getUpdateTime() {
        if (updateTime == null) {
            return "";
        }
        return updateTime;
    }

    public void setUpdateTime(String updateTime) {
        this.updateTime = updateTime;
    }

    public int getReadingArticleIndex() {
        return readingArticleIndex;
    }

    public void setReadingArticleIndex(int readingArticleIndex) {
        this.readingArticleIndex = readingArticleIndex;
    }

    public int getReadingArticleWordNum() {
        return readingArticleWordNum;
    }

    public void setReadingArticleWordNum(int readingArticleWordNum) {
        this.readingArticleWordNum = readingArticleWordNum;
    }


    /*
    获取小说目录
     */
    public List<Article> getArticles() throws DbException {
        if (mArticles != null) {
            return mArticles;
        }
        mArticles = DbUtil.getDbManager().selector(Article.class).where("bookId", "=", this.id).orderBy("id", false).findAll();
        return mArticles;
    }

    /*
    添加小说目录
     */
    public boolean addArticles(List<ContentItem> contents) {
        if (contents == null || contents.size() == 0) {
            return false;
        }
        List<Article> articles = new ArrayList<>();
        try {
            for (ContentItem item : contents) {
                Article article = new Article();
                article.setBookId(this.getId());
                article.setTitle(item.getContentTitle());
                article.setUrl(item.getUrl());
                article.setDownload(false);
                article.setRead(false);
                articles.add(article);
            }
            DbUtil.getDbManager().save(articles);
            mArticles = null;
        } catch (DbException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /*
    更新小说目录
     */
    public boolean updateArticles() {
        try {
            List<Article> list = getArticles();
            if (list == null || list.size() == 0) {
                return false;
            }
            //旧章节数
            int oldSize = list.size();
            Website website = WebsiteMgr.getManager().getWebsite(this.getSite());
            if (website == null) {
                return false;
            }
            String contentsHtml = HttpUtil.getStringFromUrl(this.getContentsUrl(), website.getUserAgent(), this.getSite(), null);
            Document document = Jsoup.parse(contentsHtml, this.getContentsUrl());
            if (document == null) {
                return false;
            }
            List<ContentItem> newList = NovelUtil.parseContents(document, website);
            if (newList == null) {
                return false;
            }
            int newSize = newList.size(); //新章节数
            if (newSize < oldSize) {    //出错
                return false;
            }
            if (newSize == oldSize) {   //无更新
                return true;
            }

            this.setUpdateTag(true);
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            this.setUpdateTime(dateFormat.format(new Date()));
            DbUtil.getDbManager().saveOrUpdate(this);
            //截取更新章节
            List<ContentItem> updateList = newList.subList(oldSize, newSize);
            return addArticles(updateList);

        } catch (DbException e) {
            e.printStackTrace();
            return false;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }

    /*
    下载剩余未缓存章节内容
     */
    public boolean downloadRemainderArticleContent() {
        try {
            List<Article> list = getArticles();
            for (Article article : list) {
                if (article.isDownload()) {
                    continue;
                }
                downloadArticleContent(article);
            }
            return true;
        } catch (DbException e) {
            e.printStackTrace();
            return false;
        }
    }

    /*
    删除目录和章节内容
     */
    public void removeArticleAll() {
        try {
            //删除章节内容
            DbUtil.getDbManager().delete(ArticleContent.class, WhereBuilder.b("bookId", "=", this.getId()));
        } catch (DbException e) {
            e.printStackTrace();
        }

        try {
            //删除章节内容
            DbUtil.getDbManager().delete(Article.class, WhereBuilder.b("bookId", "=", this.getId()));
        } catch (DbException e) {
            e.printStackTrace();
        }
    }

    /*
    下载章节内容
     */
    public boolean downloadArticleContent(Article article) {
        if (article == null) {
            return false;
        }
        String content = NovelUtil.getArticleContent(article.getUrl(), WebsiteMgr.getManager().getWebsite(getSite()));
        if (content == null || content.length() == 0) {
            return false;
        }
        ArticleContent articleContent = new ArticleContent();
        articleContent.setBookId(this.getId());
        articleContent.setArticleId(article.getId());
        articleContent.setContent(content);
        try {
            DbUtil.getDbManager().save(articleContent);
            article.setDownload(true);
            article.setRead(false);
            article.setDownloadTime(DateUtil.getSqliteDateTime(null));
            DbUtil.getDbManager().saveOrUpdate(article);
        } catch (DbException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /*
    获取章节内容
     */
    public String getArticleContent(Article article, boolean isTraditional) {
        if (article == null) {
            return null;
        }
        try {
            ArticleContent content = DbUtil.getDbManager().selector(ArticleContent.class).where("articleId", "=", article.getId()).findFirst();
            String text = content.getContent();
            if (isTraditional) {
                try {
                    return JChineseConvertor.getInstance().s2t(text);
                } catch (IOException e) {
                    e.printStackTrace();
                    return text;
                }
            }
            return text;
        } catch (DbException e) {
            e.printStackTrace();
            return null;
        }
    }

    /*
    设置小说封面
     */
    @BindingAdapter("cover")
    public static void loadInternetImage(ImageView iv, String imgUrl) {
//        Picasso.with(iv.getContext()).load(imgUrl).error(R.drawable.nocover).placeholder(R.drawable.nocover).into(iv);
        RequestOptions options = new RequestOptions()
                .centerCrop()
                .placeholder(R.drawable.nocover)
                .error(R.drawable.nocover)
                .priority(Priority.HIGH)
                .diskCacheStrategy(DiskCacheStrategy.ALL);
        Glide.with(iv.getContext())
                .load(imgUrl)
                .apply(options)
                .into(iv);
    }

    public String toString() {
        String string = "State:" + state + "\nType:" + type;
        return string;
    }

    @Override
    public int compareTo(@NonNull Object o) {
        Book anotherBook = (Book) o;
        String sortType = Config.getSortType();
        String anotherReadTime = anotherBook.getReadTime();
        String anotherUpdateTime = anotherBook.getUpdateTime();
        if (sortType.equals(Config.SORT_TYPE_READ)) {
            int ret = compareStr(readTime, anotherReadTime);
            return ret;
        } else if (sortType.equals(Config.SORT_TYPE_UPDATE)) {
            int ret = compareStr(updateTime, anotherUpdateTime);
            return ret;
        }
        return 0;
    }
    private int compareStr(String str1, String str2) {
        if (str1 == null && str2 == null) {
            return 0;
        }
        if (str1 == null) {
            return 1;
        }
        if (str2 == null) {
            return -1;
        }
        int len1 = str1.length();
        int len2 = str2.length();
        int min = len1 < len2 ?len1:len2;

        if (min == 0) {
            if (len1 == 0 && len2 == 0) {
                return 0;
            }
            if (len1 < len2) {
                return 1;
            } else {
                return -1;
            }
        }

        int i = 0;
        for (i = 0; i < min; i++) {
            char c1 = str1.charAt(i);
            char c2 = str2.charAt(i);
            if (c1 < c2) {
                return 1;
            } else if (c1 > c2){
                return -1;
            }
        }
        if (i == min - 1) {
            if (len1 < len2) {
                return 1;
            } else {
                return -1;
            }
        }
        return 0;
    }
}
